`timescale 1ps / 1ps
module mips(
	input clk,
	input rst
	);

	//ctrl
	wire [1:0]RegWr;
	wire RegDst,ExtOp,ALUsrc;
	wire [2:0]Branch;
	wire [1:0]MemWr;
	wire MemtoReg;
	wire [3:0] ALUctr;
	wire [4:0] Rs,Rt,Rd;
	
	
	//np&npc
	wire[31:0] NPC,PC;
	
	//ALU
	wire [31:0] Zero;
	wire OF;
	wire [31:0] B,result;


	//dm
	wire [31:0]DataOut;

	//im
	wire [31:0]ins;

	//EXT
	wire [15:0] imm16;
	wire [31:0] imm32;

	//Registers
	wire[4:0] Rw;
	wire[31:0] busA, busB, busW;

	//shift
	wire[4:0] shf;
	wire ALUshf;

	//JUMP
	wire [1:0]Jump; wire R31wr;
	wire [31:0]Bnpc;

//****From Left to Right****//
//*
//*                      |----->----|
//*      npc<->pc->im->IF_ID<->ctrl -->register->ID_EX->ALU->EX_MEM->DM->MEM/WR
//*										  |--<----------<----------<---------|
//*
//*
	pc A_pc(.npc(NPC),.pc(PC),.clk(clk),.reset(rst));
	npc A_npc(.npc(NPC),.pc(PC),.Bnpc(Bnpc),.Branch(Branch),.Jump(Jump),.Zero(Zero),.imm32(imm32),.busA(busA));

	im A_im(.pc(PC),.instruction(ins));

	//* IF_ID//
	wire [4:0] ID_Rs,ID_Rt,ID_Rd,ID_shf;
	wire [15:0] ID_imm16;
	wire [31:0] ID_bnpc,ID_pc,ID_ins;
	wire [3:0] ID_ALUctr;
	wire [2:0] ID_Branch;
	wire [1:0] ID_Jump,ID_RegWr,ID_MemWr;
	wire ID_RegDst,ID_ExtOp,ID_ALUsrc,ID_MemtoReg,ID_ALUshf,ID_R31wr;
	IF_ID IF_ID(
		clk,Rs,Rt,Rd,shf,PC,Bnpc,ins,ALUctr,Branch,Jump,RegWr,RegDst,ExtOp,ALUsrc,MemWr,MemtoReg,ALUshf,R31wr,
		ID_Rs,ID_Rt,ID_Rd,ID_shf,ID_pc,ID_bnpc,ID_ins,ID_ALUctr,ID_Branch,ID_Jump,ID_RegWr,ID_RegDst,ID_ExtOp,ID_ALUsrc,ID_MemWr,ID_MemtoReg,ID_ALUshf,ID_R31wr
	);

	ctrl MAIN(ID_ins,Rs,Rt,Rd,imm16,shf,ALUctr,Branch,Jump,RegWr,RegDst,ExtOp,ALUsrc,MemWr,MemtoReg,ALUshf,R31wr);

	Registers A_Reg(
		.clk(clk),.RegWr(ID_RegWr),.Ra(ID_Rs),.Rb(ID_Rt),.Rw(Rw),
		.busA(busA),.busB(busB),.busW(busW),
		.Bnpc(ID_bnpc),.R31wr(ID_R31wr)
	);
	
	//* ID_EX //
	wire [31:0] pc,ins;
	wire [3:0] ALUctr;
	wire [2:0] Branch;
	wire [1:0] Jump,RegWr,MemWr;
	wire RegDst,ExtOp,ALUsrc,MemtoReg,ALUshf,R31wr;
	ID_EX ID_EX();

	alu A_ALU(.ALUctr(ALUctr),.A(busA),.B(B),.result(result),.Zero(Zero),.OF(OF),.shf(shf),.ALUshf(ALUshf));
	MUX ALUMux(.control(ALUsrc),.a(busB),.b(imm32),.result(B));
	MUX RegMux(.control(RegDst),.a(Rt),.b(Rd),.result(Rw));
	Ext A_ext(.ExtOp(ExtOp),.in(imm16),.out(imm32));


	//* EX_MEM //
	wire [31:0] pc,ins;
	wire [3:0] ALUctr;
	wire [2:0] Branch;
	wire [1:0] Jump,RegWr,MemWr;
	wire RegDst,ExtOp,ALUsrc,MemtoReg,ALUshf,R31wr;
	EX_MEM EX_MEM();


	dm A_dm(.clk(clk),.RegWr(RegWr),.DataIn(busB),.Address(result),.DataOut(DataOut),.MemWr(MemWr));


	MUX DMux(.control(MemtoReg),.a(result),.b(DataOut),.result(busW));



endmodule
